<template>
  <canvas
    ref="canvasRef"
    class="background-canvas"
    :class="{ 'canvas-disabled': backgroundEffect === 'none' }"
  ></canvas>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
import { useThemeStore, type BackgroundEffect } from '@/stores/theme'

const themeStore = useThemeStore()
const canvasRef = ref<HTMLCanvasElement>()
let ctx: CanvasRenderingContext2D | null = null
let animationId: number | null = null
let particles: Particle[] = []
let mouseX = 0
let mouseY = 0
let isMouseInCanvas = false

// 响应式计算属性
const backgroundEffect = computed(() => themeStore.backgroundEffect)
const intensity = computed(() => themeStore.backgroundEffectIntensity)
const isDark = computed(() => themeStore.isDark)

// 粒子类
class Particle {
  x: number
  y: number
  vx: number
  vy: number
  size: number
  opacity: number
  color: string

  constructor(canvas: HTMLCanvasElement, isDark: boolean) {
    this.x = Math.random() * canvas.width
    this.y = Math.random() * canvas.height
    this.vx = (Math.random() - 0.5) * 0.5
    this.vy = (Math.random() - 0.5) * 0.5
    this.size = Math.random() * 2 + 1
    this.opacity = isDark ? Math.random() * 0.5 + 0.3 : Math.random() * 0.7 + 0.4
    this.color = isDark ? 'rgba(255, 255, 255, ' : 'rgba(50, 50, 50, '
  }

  update(canvas: HTMLCanvasElement) {
    this.x += this.vx
    this.y += this.vy

    if (this.x < 0 || this.x > canvas.width) this.vx *= -1
    if (this.y < 0 || this.y > canvas.height) this.vy *= -1
  }

  draw(ctx: CanvasRenderingContext2D, isDark: boolean) {
    ctx.save()

    // 在日间模式下添加阴影效果
    if (!isDark) {
      ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'
      ctx.shadowBlur = 3
      ctx.shadowOffsetX = 1
      ctx.shadowOffsetY = 1
    }

    ctx.beginPath()
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    ctx.fillStyle = this.color + this.opacity + ')'
    ctx.fill()
    ctx.restore()
  }

  // 计算与其他粒子的距离
  distanceTo(other: Particle): number {
    const dx = this.x - other.x
    const dy = this.y - other.y
    return Math.sqrt(dx * dx + dy * dy)
  }

  // 计算与鼠标的距离
  distanceToMouse(mouseX: number, mouseY: number): number {
    const dx = this.x - mouseX
    const dy = this.y - mouseY
    return Math.sqrt(dx * dx + dy * dy)
  }
}



// 气泡效果
class Bubble {
  x: number
  y: number
  radius: number
  speed: number
  opacity: number
  color: string
  wobble: number

  constructor(canvas: HTMLCanvasElement, isDark: boolean) {
    this.x = Math.random() * canvas.width
    this.y = Math.random() * canvas.height // 在整个屏幕范围内随机分布
    this.radius = Math.random() * 20 + 5
    this.speed = Math.random() * 1.2 + 0.2
    this.opacity = isDark ? Math.random() * 0.6 + 0.1 : Math.random() * 0.8 + 0.3
    this.wobble = Math.random() * Math.PI * 2
    this.color = isDark
      ? `rgba(120, 180, 255, ${this.opacity})`
      : `rgba(40, 100, 180, ${this.opacity})`
  }

  update(canvas: HTMLCanvasElement) {
    this.y -= this.speed
    this.wobble += 0.02
    this.x += Math.sin(this.wobble) * 0.8

    // 边界检查
    if (this.x < -this.radius) this.x = canvas.width + this.radius
    if (this.x > canvas.width + this.radius) this.x = -this.radius

    // 循环边界处理
    if (this.y < -this.radius) {
      this.y = canvas.height + this.radius
      this.x = Math.random() * canvas.width
      this.wobble = Math.random() * Math.PI * 2
    }
  }

  draw(ctx: CanvasRenderingContext2D) {
    ctx.save()
    ctx.globalAlpha = this.opacity

    // 绘制气泡外圈
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
    ctx.strokeStyle = this.color
    ctx.lineWidth = 2
    ctx.stroke()

    // 绘制气泡内部高光
    ctx.beginPath()
    ctx.arc(this.x - this.radius * 0.3, this.y - this.radius * 0.3, this.radius * 0.2, 0, Math.PI * 2)
    ctx.fillStyle = this.color.replace(/[\d.]+\)$/, '0.6)')
    ctx.fill()

    ctx.restore()
  }
}

// 贪吃蛇效果
class Snake {
  body: { x: number, y: number }[]
  direction: { x: number, y: number }
  speed: number
  color: string
  opacity: number
  maxLength: number
  changeDirectionTimer: number
  changeDirectionInterval: number

  constructor(canvas: HTMLCanvasElement, isDark: boolean) {
    // 随机起始位置
    this.body = [{
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height
    }]

    // 随机初始方向
    const angle = Math.random() * Math.PI * 2
    this.speed = 1 + Math.random() * 2
    this.direction = {
      x: Math.cos(angle) * this.speed,
      y: Math.sin(angle) * this.speed
    }

    this.maxLength = 15 + Math.random() * 25
    this.opacity = isDark ? Math.random() * 0.6 + 0.3 : Math.random() * 0.8 + 0.4
    this.color = isDark
      ? `rgba(120, 180, 255, `
      : `rgba(50, 120, 200, `

    this.changeDirectionTimer = 0
    this.changeDirectionInterval = 60 + Math.random() * 120 // 1-3秒改变方向
  }

  update(canvas: HTMLCanvasElement) {
    // 移动头部
    const head = this.body[0]
    const newHead = {
      x: head.x + this.direction.x,
      y: head.y + this.direction.y
    }

    // 边界处理 - 穿越边界
    if (newHead.x < 0) newHead.x = canvas.width
    if (newHead.x > canvas.width) newHead.x = 0
    if (newHead.y < 0) newHead.y = canvas.height
    if (newHead.y > canvas.height) newHead.y = 0

    this.body.unshift(newHead)

    // 保持长度
    if (this.body.length > this.maxLength) {
      this.body.pop()
    }

    // 随机改变方向
    this.changeDirectionTimer++
    if (this.changeDirectionTimer >= this.changeDirectionInterval) {
      this.changeDirection()
      this.changeDirectionTimer = 0
      this.changeDirectionInterval = 60 + Math.random() * 120
    }
  }

  changeDirection() {
    // 随机改变方向，但不会完全反向
    const currentAngle = Math.atan2(this.direction.y, this.direction.x)
    const angleChange = (Math.random() - 0.5) * Math.PI // 最大90度转向
    const newAngle = currentAngle + angleChange

    this.direction = {
      x: Math.cos(newAngle) * this.speed,
      y: Math.sin(newAngle) * this.speed
    }
  }

  draw(ctx: CanvasRenderingContext2D) {
    ctx.save()

    // 绘制蛇身
    for (let i = 0; i < this.body.length; i++) {
      const segment = this.body[i]
      const segmentOpacity = this.opacity * (1 - i / this.body.length) * 0.8
      const segmentSize = (1 - i / this.body.length) * 4 + 2

      ctx.globalAlpha = segmentOpacity
      ctx.beginPath()
      ctx.arc(segment.x, segment.y, segmentSize, 0, Math.PI * 2)
      ctx.fillStyle = this.color + segmentOpacity + ')'
      ctx.fill()

      // 添加光晕效果
      ctx.beginPath()
      ctx.arc(segment.x, segment.y, segmentSize * 2, 0, Math.PI * 2)
      ctx.fillStyle = this.color + (segmentOpacity * 0.3) + ')'
      ctx.fill()
    }

    ctx.restore()
  }
}

// 初始化Canvas
const initCanvas = () => {
  if (!canvasRef.value) return
  
  const canvas = canvasRef.value
  ctx = canvas.getContext('2d')
  if (!ctx) return

  // 设置Canvas尺寸
  const resizeCanvas = () => {
    const rect = canvas.parentElement?.getBoundingClientRect()
    if (rect) {
      canvas.width = rect.width
      canvas.height = rect.height
    }
  }

  resizeCanvas()
  window.addEventListener('resize', resizeCanvas)

  // 添加鼠标事件监听
  canvas.addEventListener('mousemove', (e) => {
    const rect = canvas.getBoundingClientRect()
    mouseX = e.clientX - rect.left
    mouseY = e.clientY - rect.top
    isMouseInCanvas = true
  })

  canvas.addEventListener('mouseleave', () => {
    isMouseInCanvas = false
  })

  // 初始化效果
  initEffect()
  animate()
}

// 初始化效果
const initEffect = () => {
  if (!canvasRef.value || !ctx) return
  
  particles = []
  const canvas = canvasRef.value
  const particleCount = Math.floor((intensity.value / 100) * 100)

  switch (backgroundEffect.value) {
    case 'particles':
      const particlesCount = Math.floor((intensity.value / 100) * 150) + 50 // 50-200个粒子
      for (let i = 0; i < particlesCount; i++) {
        particles.push(new Particle(canvas, isDark.value))
      }
      break

    case 'bubbles':
      const bubblesCount = Math.floor((intensity.value / 100) * 30) + 10 // 10-40个气泡
      for (let i = 0; i < bubblesCount; i++) {
        particles.push(new Bubble(canvas, isDark.value))
      }
      break
    case 'grid': // 现在是贪吃蛇效果
      const snakeCount = Math.floor((intensity.value / 100) * 8) + 2 // 2-10条蛇
      for (let i = 0; i < snakeCount; i++) {
        particles.push(new Snake(canvas, isDark.value))
      }
      break
  }
}

// 动画循环
const animate = () => {
  if (!ctx || !canvasRef.value || backgroundEffect.value === 'none') return

  const canvas = canvasRef.value
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  // 更新和绘制粒子
  particles.forEach(particle => {
    if ('update' in particle) {
      particle.update(canvas)
    }
    particle.draw(ctx!, canvas)
  })

  // 粒子星空效果的连线
  if (backgroundEffect.value === 'particles') {
    drawParticleConnections()
  }

  animationId = requestAnimationFrame(animate)
}

// 绘制粒子连线
const drawParticleConnections = () => {
  if (!ctx || !canvasRef.value) return

  const maxDistance = 120
  const mouseDistance = 150

  // 粒子之间的连线
  for (let i = 0; i < particles.length; i++) {
    for (let j = i + 1; j < particles.length; j++) {
      const p1 = particles[i] as Particle
      const p2 = particles[j] as Particle
      const distance = p1.distanceTo(p2)

      if (distance < maxDistance) {
        const opacity = (1 - distance / maxDistance) * 0.3
        ctx.save()
        ctx.globalAlpha = opacity
        ctx.strokeStyle = isDark.value ? 'rgba(120, 180, 255, 0.5)' : 'rgba(40, 100, 160, 0.6)'
        ctx.lineWidth = 1
        ctx.beginPath()
        ctx.moveTo(p1.x, p1.y)
        ctx.lineTo(p2.x, p2.y)
        ctx.stroke()
        ctx.restore()
      }
    }

    // 粒子与鼠标的连线
    if (isMouseInCanvas) {
      const p = particles[i] as Particle
      const distance = p.distanceToMouse(mouseX, mouseY)

      if (distance < mouseDistance) {
        const opacity = (1 - distance / mouseDistance) * 0.6
        ctx.save()
        ctx.globalAlpha = opacity
        ctx.strokeStyle = isDark.value ? 'rgba(255, 255, 255, 0.8)' : 'rgba(30, 80, 150, 0.9)'
        ctx.lineWidth = 2
        ctx.beginPath()
        ctx.moveTo(p.x, p.y)
        ctx.lineTo(mouseX, mouseY)
        ctx.stroke()
        ctx.restore()
      }
    }
  }
}

// 停止动画
const stopAnimation = () => {
  if (animationId) {
    cancelAnimationFrame(animationId)
    animationId = null
  }
}

// 监听效果变化
watch([backgroundEffect, intensity, isDark], () => {
  if (backgroundEffect.value === 'none') {
    stopAnimation()
    if (ctx && canvasRef.value) {
      ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)
    }
  } else {
    stopAnimation()
    initEffect()
    animate()
  }
})

onMounted(() => {
  initCanvas()
})

onUnmounted(() => {
  stopAnimation()
  window.removeEventListener('resize', () => {})
})
</script>

<style lang="scss" scoped>
.background-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  opacity: 1;
  transition: opacity 0.3s ease;
  
  &.canvas-disabled {
    opacity: 0;
  }
}
</style>
